package com.shycloud.mido.homework.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.shycloud.mido.common.core.exception.BusinessException;
import com.shycloud.mido.homework.api.feign.StudentFeignService;
import com.shycloud.mido.homework.api.feign.TeacherFeignService;
import com.shycloud.mido.homework.api.vo.HomeworkDataVO;
import com.shycloud.mido.homework.api.vo.MusicRankVO;
import com.shycloud.mido.homework.api.vo.MusicSummaryStatisticVO;
import com.shycloud.mido.homework.mapper.MidoHomeworkComplateMapper;
import com.shycloud.mido.homework.mapper.MidoHomeworkMainMapper;
import com.shycloud.mido.homework.service.StatisticsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Xiaoxing Yu
 * @date 2020/11/9 11:27 上午
 **/

@Slf4j
@Service
@AllArgsConstructor
public class StatisticsServiceImpl implements StatisticsService {

	/** 作业模块 mapper */
	private MidoHomeworkMainMapper mainMapper;
	/** 作业完成情况 mapper */
	private MidoHomeworkComplateMapper complateMapper;
	/** 学生feign远程服务 mapper */
	private StudentFeignService studentFeignService;
	/** 教师feign远程服务 mapper */
	private TeacherFeignService teacherFeignService;

	/**
	 * 获取学生历史弹奏统计数据/每曲
	 *
	 * 包含数据：作业  最高分 最低分 每次分数 第一次弹分数  最晚弹琴时间  弹琴时长每日/星期/月(所有歌曲/单首曲)
	 * 达到100分用时/次数
	 *
	 * @param studentId 	 @param musicId
	 * @return com.shycloud.mido.homework.api.vo.MusicSummaryStatisticVO
	 * @author xiaoxing.yu
	 * @date 2020/11/9 1:38 下午
	 */
	@Override
	public MusicSummaryStatisticVO getSummaryStatistics(String studentId, Integer musicId) {
		Integer maxScore = null;
		Integer minScore = null;
		Integer totalScore = 0;
		Double averageScore = 0.0;
		Calendar latestTimeOfDay = null;
		MusicSummaryStatisticVO statisticVO = null;
		List<Map<String, Map<Object, Long>>> playTimeList = null;
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		try {
			List<String> teacherIdList = teacherFeignService.getTeacherIdsByStudentId(studentId);

			//按照提交完成作业时间升序
			List<HomeworkDataVO> taskList = new ArrayList<>();

			if (teacherIdList == null || teacherIdList.size() == 0) {
				taskList = mainMapper.getSummaryStatistics(studentId, musicId, null);
			} else {
				taskList.addAll(mainMapper.getSummaryStatistics(studentId, musicId, null));
				for (String teacherId: teacherIdList) {
					taskList.addAll(mainMapper.getSummaryStatistics(studentId, musicId, teacherId));
				}
			}

			if (taskList == null || taskList.size() == 0) {
				throw new BusinessException("未找到该学生此曲目作业的完成记录！");
			}

			playTimeList = new ArrayList<>();
			for (int i = 0; i< taskList.size(); i++) {
				Date initDate = taskList.get(i).getFinishTime();
				if (initDate != null && latestTimeOfDay == null) {
					latestTimeOfDay = Calendar.getInstance();
					latestTimeOfDay.setTime(initDate);
					break;
				}
			}

			Map<String, Map<Object, Long> > playTimeMap = new HashMap();
			Map<Object, Long> dayAccTimeMap = new HashMap();
			Map<Object, Long> monthAccTimeMap = new HashMap();
			Map<Object, Long> yearAccTimeMap = new HashMap();
			Map<Object, Long> weekAccTimeMap = new HashMap();
			playTimeMap.put("dayAccTime", dayAccTimeMap);
			playTimeMap.put("monthAccTime", monthAccTimeMap);
			playTimeMap.put("yearAccTime", yearAccTimeMap);
			playTimeMap.put("weekAccTime", weekAccTimeMap);
			playTimeList.add(playTimeMap);

			statisticVO = new MusicSummaryStatisticVO();
			statisticVO.setFirstTimeScore(taskList.get(0).getTotalScore());

			minScore = taskList.get(0).getTotalScore();
			maxScore = taskList.get(0).getTotalScore();

			for (int i = 0; i < taskList.size(); i++) {
				Integer curScore = taskList.get(i).getTotalScore();

				if (curScore > maxScore) {
					maxScore = curScore;
				} else if (curScore < minScore) {
					minScore = curScore;
				}

				totalScore += curScore;

				if (taskList.get(i).getFinishTime() != null) {
					if (latestTimeOfDay != null) {
						Date playDate = taskList.get(i).getFinishTime();
						String dateStr = dateFormat.format(playDate);
						Calendar playTimeOfDay = Calendar.getInstance();
						playTimeOfDay.set(Calendar.SECOND, getSecond(dateStr));
						playTimeOfDay.set(Calendar.MINUTE, getMinite(dateStr));
						playTimeOfDay.set(Calendar.HOUR_OF_DAY, getHour(dateStr));

						String latestDateStr = dateFormat.format(latestTimeOfDay.getTime());

						setCalendar(playTimeOfDay, latestDateStr);

						if (playTimeOfDay.compareTo(latestTimeOfDay) > 0) {
							latestTimeOfDay = playTimeOfDay;
							setCalendar(playTimeOfDay, dateStr);
						}
					}

					if (taskList.get(i).getPlayTime() != null) {
						String timeStr = dateFormat.format(taskList.get(i).getFinishTime());
						Integer playTime = taskList.get(i).getPlayTime();
						dealWithTimeMap(playTimeMap, timeStr, playTime);
					}
				}
			}

			averageScore = new BigDecimal(totalScore).divide(new BigDecimal(taskList.size())).doubleValue();
			statisticVO.setAverageScore(averageScore);

			statisticVO.setPlayTimeList(playTimeList);
			statisticVO.setMaxScore(maxScore);
			statisticVO.setMinScore(minScore);
			statisticVO.setLatestSubmitTime(dateFormat.format(latestTimeOfDay.getTime()));
			statisticVO.setStudentId(studentId);
			statisticVO.setMusicId(musicId);
			if (taskList.get(0).getMusicName() != null) statisticVO.setMusicName(taskList.get(0).getMusicName());
			LinkedHashMap studentInfoMap = (LinkedHashMap)studentFeignService.getStudentDetail(studentId).getData();

			if (studentInfoMap != null) statisticVO.setStudentName((String)studentInfoMap.get("showName"));
		} catch (BusinessException e) {
			log.error(e.getMessage(), e);
			throw e;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		return statisticVO;
	}

	@Override
	public List<MusicRankVO> getMusicRank(Integer musicId) {
		List<MusicRankVO> rankVOList = complateMapper.getMusicRank(musicId, 10);
		return rankVOList;
	}

	private void dealWithTimeMap(Map<String, Map<Object, Long>> playTimeMap, String timeStr, Integer playTime) throws Exception {
		Map<Object, Long> dayAccTimeMap = playTimeMap.get("dayAccTime");
		Map<Object, Long> monthAccTimeMap = playTimeMap.get("monthAccTime");
		Map<Object, Long> yearAccTimeMap = playTimeMap.get("yearAccTime");
		Map<Object, Long> weekAccTimeMap = playTimeMap.get("weekAccTime");

		Integer day = getDay(timeStr);
		Integer month = getMonth(timeStr);
		Integer year = getYear(timeStr);
		Integer week = getWeek(timeStr);
		String dayKey = year + "-" + month + "-" + day;
		String monthKey = year + "-" + month;
		String yearKey = year.toString();
		String weekKey = year + "-" + month + "_" + week;

		dayAccTimeMap.put(dayKey, dayAccTimeMap.containsKey(dayKey) ? dayAccTimeMap.get(dayKey) + playTime : playTime);
		monthAccTimeMap.put(monthKey, monthAccTimeMap.containsKey(monthKey) ? monthAccTimeMap.get(monthKey) + playTime : playTime);
		yearAccTimeMap.put(yearKey, yearAccTimeMap.containsKey(yearKey) ? yearAccTimeMap.get(yearKey) + playTime : playTime);
		weekAccTimeMap.put(weekKey, weekAccTimeMap.containsKey(weekKey) ? weekAccTimeMap.get(weekKey) + playTime : playTime);
	}

	private Integer getHour(String dateStr) {
		return Integer.valueOf(dateStr.substring(11).split(":")[0]);
	}

	private Integer getMinite(String dateStr) {
		return Integer.valueOf(dateStr.substring(11).split(":")[1]);
	}

	private Integer getSecond(String dateStr) {
		return Integer.valueOf(dateStr.substring(11).split(":")[2]);
	}

	private Integer getMonth(String dateStr) {
		return Integer.valueOf(dateStr.substring(0, 10).split("-")[1]);
	}

	private Integer getDay(String dateStr) {
		return Integer.valueOf(dateStr.substring(0, 10).split("-")[2]);
	}

	private Integer getYear(String dateStr) {
		return Integer.valueOf(dateStr.substring(0, 10).split("-")[0]);
	}

	//获取一年的第几周
	private Integer getWeek(String dateStr) throws Exception {
		String today = "2010-01-11";
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date date = format.parse(today);
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.setTime(date);
		return calendar.get(Calendar.WEEK_OF_YEAR);
	}

	private void setCalendar(Calendar playTimeOfDay, String dateStr) {
		playTimeOfDay.set(Calendar.DAY_OF_MONTH, getDay(dateStr));
		playTimeOfDay.set(Calendar.MONTH, getMonth(dateStr));
		playTimeOfDay.set(Calendar.YEAR, getYear(dateStr));
	}

}
